﻿using System;
using Microsoft.Maps.MapControl;
using System.Windows;
using System.Collections.Generic;
using MyFloridaHouse.ServiceConn.DistrBldrSvcRef;
using MyFloridaHouse.libSvUtilities.Logging;
using MyFloridaHouse.libSvOpenDistricts.Criteria;

namespace MyFloridaHouse.libSvOpenDistricts.DataService
{
    public delegate void ServiceDALGetRegionIDsInViewCompletedEventHandler(RegionIDsSTO args);
    public delegate void ServiceDALGetRegionIDsInViewErrorEventHandler(int layerID, Exception ex);

    public struct PendingGetRegionIDsInViewRequest
    {
        public int layerID;
        public LocationRect viewWindow;
    }

    public partial class ServiceDAL
    {
        public static event ServiceDALGetRegionIDsInViewCompletedEventHandler GetRegionIDsInViewCompleted;
        public static event ServiceDALGetRegionIDsInViewErrorEventHandler GetRegionIDsInViewError;

        public void GetRegionIDsInView(int layerID, LocationRect viewWindow)
        {
            try
            {
                if (getGetRegionIDsInViewCount(layerID) > 0)
                {
                    PendingGetRegionIDsInViewRequest rqst = new PendingGetRegionIDsInViewRequest();
                    rqst.layerID = layerID;
                    rqst.viewWindow = viewWindow;
                    addGetRegionIDsInViewPendingRequest(layerID, rqst);
                }
                else
                {
                    //MyDistrictBuilderServiceClient proxy = new MyDistrictBuilderServiceClient(myRelativeBinding, myRelativeCensusDataServiceAddress);
					var proxy = new DistrBldrClient(_relativeBindingName);
                    proxy.GetRegionIDsInViewCompleted += ServiceGetRegionIDsInViewCompleted;
                    proxy.GetRegionIDsInViewAsync( layerID, viewWindow.North, viewWindow.East, viewWindow.South, viewWindow.West);
                    incrementGetRegionIDsInViewActiveCount(layerID);
                }
            }
            catch (Exception ex)
            {
                RaiseGetRegionIDsInViewError(this, layerID, ex);
            }
        }

        private void ServiceGetRegionIDsInViewCompleted(object sender, GetRegionIDsInViewCompletedEventArgs args)
        {
            decrementGetRegionIDsInViewActiveCount(args.Result.layerID);
            if (!IsError("GetRegionIDsInViewCompleted", args.Error, args.Result, args.Result.errorMessage))
            {

                // only bother mapping if this is the last request we sent
                if (IsGetRegionIDsInViewPendingRequest(args.Result.layerID))
                {
                    PendingGetRegionIDsInViewRequest rqst = removeGetRegionIDsInViewPendingRequest(args.Result.layerID);
                    GetRegionIDsInView( rqst.layerID,rqst.viewWindow);
                }
                else
                {
                    RaiseGetRegionIDsInViewCompleted(this, args.Result);
                }

            }
        }

        private static void RaiseGetRegionIDsInViewCompleted(object sender, RegionIDsSTO sto)
        {
            if (GetRegionIDsInViewCompleted != null)
            {
                GetRegionIDsInViewCompleted(sto);
            }
            else
            {
                Log.HandleInternalError("No Subscribers to GetRegionIDsInViewCompleted Event, you may need to restart application");
            }
        }

        private static void RaiseGetRegionIDsInViewError(object sender, int layerID, Exception ex)
        {
            if (GetRegionIDsInViewError != null)
            {
                GetRegionIDsInViewError(layerID, ex);
            }
            else
            {
                Log.HandleInternalError("No Subscribers to GetRegionIDsInViewError Event, you may need to restart application: " + ex.Message);
            }
        }

        public int GetRegionIDsInViewRequestActiveCount
        {
            get { return GetRegionIDsInViewCountByLayer.Count; }

        }

        private Dictionary<int, int> GetRegionIDsInViewCountByLayer = new Dictionary<int, int>();
        private void incrementGetRegionIDsInViewActiveCount(int layerID)
        {
            if (GetRegionIDsInViewCountByLayer.ContainsKey(layerID))
            {
                GetRegionIDsInViewCountByLayer[layerID] = GetRegionIDsInViewCountByLayer[layerID] + 1;
            }
            else
            {
                GetRegionIDsInViewCountByLayer.Add(layerID, 1);
            }
            NotifyPropertyChanged("GetRegionIDsInViewRequestActiveCount");
        }
        private void decrementGetRegionIDsInViewActiveCount(int layerID)
        {
            if (GetRegionIDsInViewCountByLayer.ContainsKey(layerID))
            {
                GetRegionIDsInViewCountByLayer[layerID] = GetRegionIDsInViewCountByLayer[layerID] - 1;
                if (GetRegionIDsInViewCountByLayer[layerID] == 0)
                {
                    GetRegionIDsInViewCountByLayer.Remove(layerID);
                }
            }
            else
            {
                // it's not in the list and we don't want it there, so don't do anything
                // however, we did expect something there so there is a problem
                Log.HandleInternalError("Error decrementing count of pending GetRegionIDsInView requests, current count not found");
            }
            NotifyPropertyChanged("GetRegionIDsInViewRequestActiveCount");
        }
        private int getGetRegionIDsInViewCount(int layerID)
        {
            if (GetRegionIDsInViewCountByLayer.ContainsKey(layerID))
            {
                return GetRegionIDsInViewCountByLayer[layerID];
            }
            else
            {
                return 0;
            }
        }

        public int GetRegionIDsInViewRequestPendingCount
        {
            get { return pendingGetRegionIDsInViewRequests.Count; }
        }

        private Dictionary<int, PendingGetRegionIDsInViewRequest> pendingGetRegionIDsInViewRequests = new Dictionary<int, PendingGetRegionIDsInViewRequest>();
        private void addGetRegionIDsInViewPendingRequest(int layerID, PendingGetRegionIDsInViewRequest pendingRequest)
        {
            if (pendingGetRegionIDsInViewRequests.ContainsKey(layerID))
            {
                pendingGetRegionIDsInViewRequests[layerID] = pendingRequest;

            }
            else
            {
                pendingGetRegionIDsInViewRequests.Add(layerID, pendingRequest);
            }
            NotifyPropertyChanged("GetRegionIDsInViewRequestPendingCount");
        }
        private PendingGetRegionIDsInViewRequest removeGetRegionIDsInViewPendingRequest(int layerID)
        {
            if (pendingGetRegionIDsInViewRequests.ContainsKey(layerID))
            {
                PendingGetRegionIDsInViewRequest pendingRequest = pendingGetRegionIDsInViewRequests[layerID];
                pendingGetRegionIDsInViewRequests.Remove(layerID);
                NotifyPropertyChanged("GetRegionIDsInViewRequestPendingCount");
                return pendingRequest;
            }
            else
            {
                // it's not in the list and we don't want it there, so don't do anything
                // however, we did expect something there so there is a problem
                Log.HandleInternalError("Error decrementing count of pending GetRegionIDsInView requests, current count not found");
                return new PendingGetRegionIDsInViewRequest();
            }


        }
        private bool IsGetRegionIDsInViewPendingRequest(int layerID)
        {
            if (pendingGetRegionIDsInViewRequests.ContainsKey(layerID))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


    }
}
